using System;
using UnityEngine;

namespace NL.Advanced
{
    public class CameraCorner : _ChildOf<CameraBase>
    {

        [Header("视场得坐标.本点获取得额外得弹性回归边缘")]
        public Vector3 ViewPoint;

        public float ExtentSpringWidth = 0;

        //public float Spring = 100f;
        public Vector3 Offset = Vector3.zero;

        Camera _MainCamer;



        public CameraCorner SetViewPoint(Vector2 vp)
        {
            ViewPoint = vp; return this;
        }

        float Aspect; Ray _Ray = new Ray();
        private void Start()
        {
            _Parent = GetComponentInParent<CameraBase>();

            Aspect = Camera.main.aspect;

        }
        // Update is called once per frame
        void Update()
        {
            if (_Parent == null || _Parent.Config == null) return;
            if (_Parent != null && !_Parent.Ready) return;

            var FOV = _Parent.Config.FOV;

            var matrix = Matrix4x4.Perspective(FOV, Aspect, 1, 1000);
            ViewPoint.z = 1;
            Vector3 lp = matrix.inverse.MultiplyPoint(ViewPoint); lp.z *= -1;
            Vector3 p = _Parent.transform.TransformPoint(lp);


            _Ray.origin = transform.position;
            _Ray.direction = (p - transform.position).normalized;


            //更新 位置..
            var pos = _Line_PANEL(_Ray.origin, _Ray.direction, Vector3.up, Vector3.up);


            if (pos.magnitude == float.NaN) return;
            try
            {
                if (float.IsNormal(pos.x) && float.IsNormal(pos.y) && float.IsNormal(pos.z))
                    transform.position = pos;
            }
            catch (Exception)
            {

            }

            // 是否进入弹性回归边缘..
            if (_Parent.BoundOwner == null) return;
            if (_Parent.BoundOwner.ToString() == "null") return;


            Offset = Vector3.zero;
            var bound = _Parent.BoundOwner.Bound;
            bound.extents *= (1 - _Parent.SpringWidth) + ExtentSpringWidth;
            Vector3 dpos = _Parent.BoundOwner.transform.InverseTransformPoint(transform.position);

            if (bound.Contains(dpos))
            {
                Offset = Vector3.zero; return;
            }

            //计算 边界外得 应值...
            var closet = bound.ClosestPoint(dpos);
            Offset = closet - dpos;

        }

        static Vector3 _Line_PANEL(Vector3 linepoint, Vector3 linedirect, Vector3 planeNormal, Vector3 planePoint)
        {
            float d = Vector3.Dot(planePoint - linepoint, planeNormal) / Vector3.Dot(linedirect, planeNormal);
            return d * linedirect.normalized + linepoint;
        }



        protected virtual void OnDrawGizmos()
        {

            Gizmos.color = Color.red;
            Gizmos.DrawSphere(transform.position, 0.5f);
            if (_Parent != null)
                Gizmos.DrawLine(_Parent.transform.position, transform.position);
        }
    }
}

